#include "protocol.h" 

extern u8 warnFlag;
extern u8 showMode;
extern u8 is_buzzer;

extern u8 temp_MaxV;
extern u8 temp_MinV;
extern double temp_value;

extern u8 humi_MaxV;
extern u8 humi_MinV;
extern double humi_value;

extern u8 tempStr[5];
extern u8 tempStr_Max[3];
extern u8 tempStr_Min[3];

extern u8 humiStr[5];
extern u8 humiStr_Max[3];
extern u8 humiStr_Min[3];

void Protocol_Init(Protocol *msg)
{
	msg->sendBegin 		= BGN_RESD_MSG;
	
	msg->device 				= '\0';
	msg->deviceCmd 			= '\0';
	msg->dataLen 				= '\0';
	msg->data 					= '\0';
	msg->sendEnd 				= END_RESD_MSG;
}

void Protocol_PacketMsg(Protocol *msg, u8 drive, u8 drive_cmd, u8 data_len, u8 *data)
{
	msg->sendBegin 		= BGN_RESD_MSG;
	msg->device 				= drive;
	msg->deviceCmd 		= drive_cmd;
	msg->dataLen 			= data_len;
	msg->data 					= data;
	msg->sendEnd 			= END_RESD_MSG;
	msg->checkSum     = Protocol_CheckSum(msg);
}

void Protocol_SendMsg(Protocol* msg)
{
	int i = 0;
	
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
    USART_SendData(USART1,msg->sendBegin);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
    USART_SendData(USART1,msg->device);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
    USART_SendData(USART1,msg->deviceCmd);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
    USART_SendData(USART1,msg->dataLen);
	if(msg->dataLen != 0)
	{
		for(i = 0; i < msg->dataLen; i++)
		{
			while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
			USART_SendData(USART1,msg->data[i]);
		}
	}else
	{
		while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
			USART_SendData(USART1,PROT_FULL_DATA);
	}
	
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
    USART_SendData(USART1,msg->sendEnd);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
    USART_SendData(USART1,msg->checkSum);
}

u8 Protocol_CheckSum(Protocol* msg)
{
		int i = 0;
    u8 checkSum = 0;
    Protocol_CalcuCheck(msg->sendBegin, &checkSum);
    Protocol_CalcuCheck(msg->device, &checkSum);
    Protocol_CalcuCheck(msg->deviceCmd, &checkSum);
    Protocol_CalcuCheck(msg->dataLen, &checkSum);
    if((msg->dataLen) > 0)
    {
        for(i = 0; i < msg->dataLen; i++)
        {
            Protocol_CalcuCheck(msg->data[i], &checkSum);
        }
    }else
    {
        Protocol_CalcuCheck('\0', &checkSum);
    }
    Protocol_CalcuCheck(msg->sendEnd, &checkSum);
    return checkSum;
}

u8 Protocol_CalcuCheck(u8 data, u8 *crc)
{
    int i = 0;
    u8 crc_poly = 0x07;
    *crc ^= data;

    for(i = 0; i < 8; i++)
    {
        if(*crc & 0x80)
        {
            *crc <<= 1;
            *crc ^= crc_poly;
        }else
        {
            *crc <<= 1;
        }
    }
    return (*crc & 0xFF);
}

void Protocol_RecvMsg(Protocol *msg)
{
	switch(msg->device)
  {
		case DEV_Warn: parseWarnDev(); break;
		case DEV_Mode: parseModeDev(msg); break;
    case DEV_Beep: parseBeepDev(msg); break;
		case DEV_Temp: parseTempDev(msg); break;
		case DEV_Humi: parseHumiDev(msg); break;
   }
}

void parseBeepDev(Protocol *msg)
{
	switch(msg->deviceCmd)
  {
     case CMD_BeepOn: Beep_ExecOn(); break;
     case CMD_BeepOff: Beep_ExecOff(); break;
	}
}

void Beep_ExecOn(void)
{
	Protocol msg;
	BEEP = BEEP_ON;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Beep, CMD_BeepOn, PROT_ZERO_LEN, PROT_FULL_DATA);
	Protocol_SendMsg(&msg);
}
void Beep_ExecOff(void)
{
	Protocol msg;
	BEEP = BEEP_OFF;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Beep, CMD_BeepOff, PROT_ZERO_LEN, PROT_FULL_DATA);
	Protocol_SendMsg(&msg);
}

void parseWarnDev(void)
{
	Protocol msg;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Warn, warnFlag, PROT_ZERO_LEN, PROT_FULL_DATA);
	Protocol_SendMsg(&msg);
}

void parseModeDev(Protocol *msg)
{
    switch(msg->deviceCmd)
    {
		case CMD_ModeGain: Mode_ExecGain(); break;
    case CMD_ModeData: Mode_ExecData(); break;
    case CMD_ModeTemp: Mode_ExecTemp(); break;
    case CMD_ModeHumi: Mode_ExecHumi(); break;
    }
}
void Mode_ExecGain(void)
{
	Protocol msg;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Mode, showMode, PROT_ZERO_LEN, PROT_FULL_DATA);
	Protocol_SendMsg(&msg);
}
void Mode_ExecData(void)
{
	BEEP_Tip();
	showMode = 0;
	Mode_AllValue();
}
void Mode_ExecTemp(void)
{
	BEEP_Tip();
	showMode = 1;
	Mode_TempValue();
}
void Mode_ExecHumi(void)
{
	BEEP_Tip();
	showMode = 2;
	Mode_HumiValue();
}

void parseTempDev(Protocol *msg)
{
    switch(msg->deviceCmd)
    {
    case CMD_TempReal: Temp_ExecReal(); break;
    case CMD_TempMaxV: Temp_ExecMaxV(); break;
	  case CMD_TempMinV: Temp_ExecMinV(); break;
    case CMD_TempMaxA: Temp_ExecMaxA(); break;
    case CMD_TempMaxS: Temp_ExecMaxS(); break;
    case CMD_TempMinA: Temp_ExecMinA(); break;
    case CMD_TempMinS: Temp_ExecMinS(); break;
    }
}

void Temp_ExecReal(void)
{
	Protocol msg;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Temp, CMD_TempReal, 5, tempStr);
	Protocol_SendMsg(&msg);
}
void Temp_ExecMaxV(void)
{
	Protocol msg;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Temp, CMD_TempMaxV, 3, tempStr_Max);
	Protocol_SendMsg(&msg);
}
void Temp_ExecMinV(void)
{
	Protocol msg;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Temp, CMD_TempMinV, 3, tempStr_Min);
	Protocol_SendMsg(&msg);
}

void Temp_ExecMaxA(void)
{
	BEEP_Tip();
	if(temp_MaxV < 100)
	{
		temp_MaxV+=5;
		sprintf((char*)tempStr_Max, "%d",temp_MaxV);
		OLED_ShowString(36,32,tempStr_Max);
	}
}
void Temp_ExecMaxS(void)
{
	BEEP_Tip();
	if(temp_MaxV > (temp_MinV+5))
	{
		temp_MaxV-=5;
		sprintf((char*)tempStr_Max, "%d",temp_MaxV);
		OLED_ShowString(36,32,tempStr_Max);
	}
}
void Temp_ExecMinA(void)
{
	BEEP_Tip();
	if(temp_MinV < (temp_MaxV-5))
	{
		temp_MinV+=5;
		sprintf((char*)tempStr_Min, "%d",temp_MinV);
		OLED_ShowString(100,32,tempStr_Min);
	}
}
void Temp_ExecMinS(void)
{
	BEEP_Tip();
	if(temp_MinV > 5)
	{
		temp_MinV-=5;
		sprintf((char*)tempStr_Min, "%d",temp_MinV);
		OLED_ShowString(100,32,tempStr_Min);
	}
}

void parseHumiDev(Protocol *msg)
{
    switch(msg->deviceCmd)
    {
    case CMD_HumiReal: Humi_ExecReal(); break;
    case CMD_HumiMaxV: Humi_ExecMaxV(); break;
		case CMD_HumiMinV: Humi_ExecMinV(); break;
    case CMD_HumiMaxA: Humi_ExecMaxA(); break;
    case CMD_HumiMaxS: Humi_ExecMaxS(); break;
    case CMD_HumiMinA: Humi_ExecMinA(); break;
    case CMD_HumiMinS: Humi_ExecMinS(); break;
    }
}

void Humi_ExecReal(void)
{
	Protocol msg;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Humi, CMD_HumiReal, 5, humiStr);
	Protocol_SendMsg(&msg);
}
void Humi_ExecMaxV(void)
{
	Protocol msg;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Humi, CMD_HumiMaxV, 3, humiStr_Max);
	Protocol_SendMsg(&msg);
}
void Humi_ExecMinV(void)
{
	Protocol msg;
	Protocol_Init(&msg);
	Protocol_PacketMsg(&msg, DEV_Humi, CMD_HumiMinV, 3, humiStr_Min);
	Protocol_SendMsg(&msg);
}

void Humi_ExecMaxA(void)
{
	BEEP_Tip();
	if(humi_MaxV < 100)
	{
		humi_MaxV+=5;
		sprintf((char*)humiStr_Max, "%d",humi_MaxV);
		OLED_ShowString(36,32,humiStr_Max);
	}
}
void Humi_ExecMaxS(void)
{
	BEEP_Tip();
	if(humi_MaxV > (humi_MinV+5))
	{
		humi_MaxV-=5;
		sprintf((char*)humiStr_Max, "%d",humi_MaxV);
		OLED_ShowString(36,32,humiStr_Max);
	}
}
void Humi_ExecMinA(void)
{
	BEEP_Tip();
	if(humi_MinV < (humi_MaxV-5))
	{
		humi_MinV+=5;
		sprintf((char*)humiStr_Min, "%d",humi_MinV);
		OLED_ShowString(100,32,humiStr_Min);
	}
}
void Humi_ExecMinS(void)
{
	BEEP_Tip();
	if(humi_MinV > 5)
	{
		humi_MinV-=5;
		sprintf((char*)humiStr_Min, "%d",humi_MinV);
		OLED_ShowString(100,32,humiStr_Min);
	}
}
